/**
 *  Copyright (C) 2008 Richard Hall
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the 
 *  GNU General Public License as published by the Free Software Foundation; either version 3 of the 
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
 *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with this program; if not, 
 *  see <http://www.gnu.org/licenses>.
 *
 *  Additional permission under GNU GPL version 3 section 7
 *
 *  If you modify this Program, or any covered work, by linking or combining it with [name of library] 
 *  (or a modified version of that library), containing parts covered by the terms of 
 *  [name of library's license], the licensors of this Program grant you additional permission to 
 *  convey the resulting work. {Corresponding Source for a non-source form of such a combination shall 
 *  include the source code for the parts of [name of library] used as well as that of the 
 *  covered work.}
 *
 * 
 */

package com.gpsmedia.kml;


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;


/**
 * This class is used in the creation of a new KML file. This file could be used
 * in its own right to produce basic KML files for tracking and or displaying
 * media data.
 * 
 * @author Richard Hall
 */
public class KMLWriter {

    private FileWriter filewrite;
    private String altMode;

    /**
	 * Constructor for this class
	 * 
	 * @param outputfile
	 *            The name of the file to be created.
	 * @param altMode
	 *            The type of altitude data inclusion to use.
	 */
    public KMLWriter(String outputfile, String altMode) {
        try {
            filewrite = new FileWriter(new File(outputfile));

        } catch (IOException ex) {
            ex.printStackTrace();
        }
        this.altMode = altMode;
    }

    /**
	 * Write the header.
	 * 
	 * @param name
	 *            Name of document
	 */
    public void writeHeader(String name) {
        try {
            filewrite.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
            filewrite.write("<kml xmlns=\"http://earth.google.com/kml/2.2\">\r\n");
            filewrite.write("<Document>\r\n");
            filewrite.write("  <name>" + name + "</name>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }


    }

    /** Writes the kml for camera style */
    public void writeCameraStyle() {
        try {
            //camera
            filewrite.write("  <StyleMap id=\"camera_symbol\">\r\n");
            filewrite.write("  <Pair>\r\n");
            filewrite.write("  <key>normal</key>\r\n");
            filewrite.write("  <styleUrl>#small_camera_symbol</styleUrl>\r\n");
            filewrite.write("  </Pair>\r\n");
            filewrite.write("  <Pair>\r\n");
            filewrite.write("  <key>highlight</key>\r\n");
            filewrite.write("  <styleUrl>#large_camera_symbol</styleUrl>\r\n");
            filewrite.write("  </Pair>\r\n");
            filewrite.write("  </StyleMap>\r\n");
            filewrite.write("  <Style id=\"large_camera_symbol\">\r\n");
            filewrite.write("  <IconStyle>\r\n");
            filewrite.write("  <scale>1.3</scale>\r\n");
            filewrite.write("  <Icon>\r\n");
            filewrite.write("  <href>http://maps.google.com/mapfiles/kml/shapes/camera.png</href> \r\n");
            filewrite.write("  </Icon>\r\n");
            filewrite.write("  <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\" /> \r\n");
            filewrite.write("  </IconStyle>\r\n");
            filewrite.write("  </Style>\r\n");
            filewrite.write("  <Style id=\"small_camera_symbol\">\r\n");
            filewrite.write("  <IconStyle>\r\n");
            filewrite.write("  <scale>1.1</scale> \r\n");
            filewrite.write("  <Icon>\r\n");
            filewrite.write("  <href>http://maps.google.com/mapfiles/kml/shapes/camera.png</href> \r\n");
            filewrite.write("  </Icon>\r\n");
            filewrite.write("  <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\" /> \r\n");
            filewrite.write("  </IconStyle>\r\n");
            filewrite.write("  </Style>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /** Writes the kml for audio style */
    public void writeAudioStyle() {
        try {
            filewrite.write("  <StyleMap id=\"audio_info_symbol\">\r\n");
            filewrite.write("  <Pair>\r\n");
            filewrite.write("  <key>normal</key>\r\n");
            filewrite.write("  <styleUrl>#small_audio_info_symbol</styleUrl>\r\n");
            filewrite.write("  </Pair>\r\n");
            filewrite.write("  <Pair>\r\n");
            filewrite.write("  <key>highlight</key>\r\n");
            filewrite.write("  <styleUrl>#large_audio_info_symbol</styleUrl>\r\n");
            filewrite.write("  </Pair>\r\n");
            filewrite.write("  </StyleMap>\r\n");
            filewrite.write("  <Style id=\"large_audio_info_symbol\">\r\n");
            filewrite.write("  <IconStyle>\r\n");
            filewrite.write("  <scale>1.3</scale>\r\n");
            filewrite.write("  <Icon>\r\n");
            filewrite.write("  <href>http://maps.google.com/mapfiles/kml/shapes/info.png</href> \r\n");
            filewrite.write("  </Icon>\r\n");
            filewrite.write("  <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\" /> \r\n");
            filewrite.write("  </IconStyle>\r\n");
            filewrite.write("  </Style>\r\n");
            filewrite.write("  <Style id=\"small_audio_info_symbol\">\r\n");
            filewrite.write("  <IconStyle>\r\n");
            filewrite.write("  <scale>1.1</scale> \r\n");
            filewrite.write("  <Icon>\r\n");
            filewrite.write("  <href>http://maps.google.com/mapfiles/kml/shapes/info.png</href> \r\n");
            filewrite.write("  </Icon>\r\n");
            filewrite.write("  <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\" /> \r\n");
            filewrite.write("  </IconStyle>\r\n");
            filewrite.write("  </Style>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /** Writes the kml for start style */
    public void writeStartStyle() {
        try {
            //green
            filewrite.write("  <StyleMap id=\"msn_grn-pushpin_copy1\">\r\n");
            filewrite.write("  <Pair>\r\n");
            filewrite.write("  <key>normal</key>\r\n");
            filewrite.write("  <styleUrl>#sn_grn-pushpin_copy1</styleUrl>\r\n");
            filewrite.write("  </Pair>\r\n");
            filewrite.write("  <Pair>\r\n");
            filewrite.write("  <key>highlight</key>\r\n");
            filewrite.write("  <styleUrl>#sh_grn-pushpin_copy1</styleUrl>\r\n");
            filewrite.write("  </Pair>\r\n");
            filewrite.write("  </StyleMap>\r\n");
            filewrite.write("  <Style id=\"sh_grn-pushpin_copy1\">\r\n");
            filewrite.write("  <IconStyle>\r\n");
            filewrite.write("  <scale>1.3</scale>\r\n");
            filewrite.write("  <Icon>\r\n");
            filewrite.write("  <href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href> \r\n");
            filewrite.write("  </Icon>\r\n");
            filewrite.write("  <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\" /> \r\n");
            filewrite.write("  </IconStyle>\r\n");
            filewrite.write("  </Style>\r\n");
            filewrite.write("  <Style id=\"sn_grn-pushpin_copy1\">\r\n");
            filewrite.write("  <IconStyle>\r\n");
            filewrite.write("  <scale>1.1</scale> \r\n");
            filewrite.write("  <Icon>\r\n");
            filewrite.write("  <href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href> \r\n");
            filewrite.write("  </Icon>\r\n");
            filewrite.write("  <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\" /> \r\n");
            filewrite.write("  </IconStyle>\r\n");
            filewrite.write("  </Style>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    /** Writes the kml for end style */
    public void writeEndStyle() {
        try {
            //red
            filewrite.write("  <StyleMap id=\"msn_red-pushpin_copy1\">\r\n");
            filewrite.write("  <Pair>\r\n");
            filewrite.write("  <key>normal</key>\r\n");
            filewrite.write("  <styleUrl>#sn_red-pushpin_copy1</styleUrl>\r\n");
            filewrite.write("  </Pair>\r\n");
            filewrite.write("  <Pair>\r\n");
            filewrite.write("  <key>highlight</key>\r\n");
            filewrite.write("  <styleUrl>#sh_red-pushpin_copy1</styleUrl>\r\n");
            filewrite.write("  </Pair>\r\n");
            filewrite.write("  </StyleMap>\r\n");
            filewrite.write("  <Style id=\"sh_red-pushpin_copy1\">\r\n");
            filewrite.write("  <IconStyle>\r\n");
            filewrite.write("  <scale>1.3</scale>\r\n");
            filewrite.write("  <Icon>\r\n");
            filewrite.write("  <href>http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png</href> \r\n");
            filewrite.write("  </Icon>\r\n");
            filewrite.write("  <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\" /> \r\n");
            filewrite.write("  </IconStyle>\r\n");
            filewrite.write("  </Style>\r\n");
            filewrite.write("  <Style id=\"sn_red-pushpin_copy1\">\r\n");
            filewrite.write("  <IconStyle>\r\n");
            filewrite.write("  <scale>1.1</scale> \r\n");
            filewrite.write("  <Icon>\r\n");
            filewrite.write("  <href>http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png</href> \r\n");
            filewrite.write("  </Icon>\r\n");
            filewrite.write("  <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\" /> \r\n");
            filewrite.write("  </IconStyle>\r\n");
            filewrite.write("  </Style>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /** Writes the line style */
    public void writeLineStyle() {
        try {
            filewrite.write("  <Style id=\"lineStyle\">\r\n");
            filewrite.write("    <LineStyle>\r\n");
            filewrite.write("      <color>64eeee17</color>\r\n");
            filewrite.write("      <width>6</width>\r\n");
            filewrite.write("    </LineStyle>\r\n");
            filewrite.write("  </Style>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();

        }

    }

    /**
	 * Writes the folder name for use in Google Earth
	 * 
	 * @param folderName
	 *            The name of the Google Earth folder
	 */
    public void writeFolderHeader(String folderName) {
        try {
            filewrite.write("  <Folder id=\"layer 0\">\r\n");
            filewrite.write("   <name>" + folderName + "</name>\r\n");
            filewrite.write("   <open>1</open>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /** Writes a close to a Google Earth folder */
    public void writeFolderClose() {
        try {
            filewrite.write("  </Folder>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    /**
	 * Adds a media file to the kml
	 * 
	 * @param isPicture
	 *            Boolean true or false
	 * @param name
	 *            Name of media
	 * @param path
	 *            Path to media
	 * @param date
	 *            Date of media
	 * @param dispLongitude
	 *            The display Londititude
	 * @param dispLatitude
	 *            The display Latitude
	 * @param description
	 *            The description
	 * @param decLongitude
	 *            The decimal Longitude
	 * @param decLatitude
	 *            The decimal Latitude
	 * @param altitude
	 *            The altitude
	 * @param uploadMedia
	 *            Has media been uploaded or not . Boolean true or false
	 */
    public void addMedia(boolean isPicture, String name, String path, String date, String dispLongitude,
            String dispLatitude, String description, String decLongitude, String decLatitude, double altitude, boolean uploadMedia) {
        try {
            filewrite.write("    <Placemark>\r\n");
            filewrite.write("     <name>" + name + "</name>\r\n");
            filewrite.write("     <description>\r\n");

            filewrite.write("      <![CDATA[");

            if (isPicture) {


                filewrite.write("       <img src=\"" + path + "\" height=\"400\" /><br/>\r\n");
            } else {
                if (uploadMedia) {
                    filewrite.write("<embed src= \"http://www.odeo.com/flash/audio_player_standard_gray.swf\" quality=\"high\" width=\"300\" \r\n");
                    filewrite.write("height=\"52\" allowScriptAccess=\"always\" wmode=\"transparent\"  type=\"application/x-shockwave-flash\" \r\n");
                    filewrite.write("flashvars= \"valid_sample_rate=true&external_url=" + path + "\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\">\r\n");
                    filewrite.write("<br/>If your system cannot display Flash. <a href=\"" + path + "\">Click to play file</a><br/></embed><br/>\r\n");
                } else {

                    filewrite.write("<a href=\"" + path + "\">Click to play file</a><br/>");

                }
            }

            filewrite.write("<B>Datetime:</B>" + date + "<br/>\r\n");
            filewrite.write("<B>Longitude:</B>" + dispLongitude + "<br/>\r\n");
            filewrite.write("<B>Latitude:</B>" + dispLatitude + "<br/>\r\n");
            filewrite.write("<B>Altitude:</B>" + altitude + " metres\r\n");

            filewrite.write("<br/><B>Description:</B><br/>\r\n");
            filewrite.write(description + "<br/>\r\n");
            filewrite.write("]]>\r\n");
            filewrite.write("     </description>\r\n");
            filewrite.write("     <LookAt>\r\n");
            filewrite.write("      <longitude>" + decLongitude + "</longitude>\r\n");
            filewrite.write("      <latitude>" + decLatitude + "</latitude>\r\n");
            filewrite.write("      <altitude>" + altitude + "</altitude>\r\n");
            filewrite.write("      <range>1500</range>\r\n");
            filewrite.write("      <tilt>-1.13</tilt>\r\n");
            filewrite.write("      <heading>1.17</heading>\r\n");
            filewrite.write("     </LookAt>\r\n");
            if (isPicture) {
                filewrite.write("     <styleUrl>#camera_symbol</styleUrl>\r\n");
            } else {
                filewrite.write("     <styleUrl>#audio_info_symbol</styleUrl>\r\n");

            }
            filewrite.write("     <Point>\r\n");
            filewrite.write("       <altitudeMode>" + altMode + "</altitudeMode>\r\n");

            filewrite.write("     <coordinates>" + decLongitude + "," + decLatitude + "," + altitude + "</coordinates>\r\n");
            filewrite.write("     </Point>\r\n");
            filewrite.write("    </Placemark>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
	 * Writes a folder to indicate the start position or end position.
	 * 
	 * @param isStart
	 *            Boolean true or false
	 * @param date
	 *            The date
	 * @param dispLongitude
	 *            The display Longitude
	 * @param dispLatitude
	 *            The display Latitude
	 * @param decLongitude
	 *            The decimal Longitude
	 * @param decLatitude
	 *            The decimal Latitude
	 * @param altitude
	 *            The altitude
	 */
    public void writeStartEndFolder(boolean isStart, String date, String dispLongitude, String dispLatitude, String decLongitude, String decLatitude, double altitude) {
        try {

            if (isStart) {
                writeFolderHeader("Start location");
                filewrite.write("    <Placemark>\r\n");
                filewrite.write("     <name>Start Location</name>\r\n");
                filewrite.write("     <description>\r\n");

                filewrite.write("      <![CDATA[<u><b>Start Location</b></u><br/>\r\n");
            } else {
                writeFolderHeader("Finish location");
                filewrite.write("    <Placemark>\r\n");
                filewrite.write("     <name>Finish Location</name>\r\n");
                filewrite.write("     <description>\r\n");

                filewrite.write("      <![CDATA[<u><b>Finish Location</b></u><br/>\r\n");
            }






            filewrite.write("<B>Datetime:</B>" + date + "<br/>\r\n");
            filewrite.write("<B>Altitude:</B>" + altitude + " metres<br/>\r\n");

            filewrite.write("<B>Longitude:</B>" + dispLongitude + "<br/>\r\n");
            filewrite.write("<B>Latitude:</B>" + dispLatitude + "<br/>\r\n");

            filewrite.write("]]>\r\n");
            filewrite.write("     </description>\r\n");
            filewrite.write("     <LookAt>\r\n");
            filewrite.write("      <longitude>" + decLongitude + "</longitude>\r\n");
            filewrite.write("      <latitude>" + decLatitude + "</latitude>\r\n");
            filewrite.write("      <altitude>" + altitude + "</altitude>\r\n");
            filewrite.write("      <range>1500</range>\r\n");
            filewrite.write("      <tilt>-1.13</tilt>\r\n");
            filewrite.write("      <heading>1.17</heading>\r\n");
            filewrite.write("     </LookAt>\r\n");

            if (isStart) {
                filewrite.write("     <styleUrl>#msn_grn-pushpin_copy1</styleUrl>\r\n");
            } else {
                filewrite.write("     <styleUrl>#msn_red-pushpin_copy1</styleUrl>\r\n");
            }

            filewrite.write("     <Point>\r\n");
            filewrite.write("       <altitudeMode>" + altMode + "</altitudeMode>\r\n");

            filewrite.write("     <coordinates>" + decLongitude + "," + decLatitude + "," + altitude + "</coordinates>\r\n");
            filewrite.write("     </Point>\r\n");
            filewrite.write("    </Placemark>\r\n");
            writeFolderClose();
        } catch (IOException ex) {
            ex.printStackTrace();
        }



    }

    /** Writes the header to the "path" section of the kml file */
    public void writePointsHeader() {
        try {
            filewrite.write("  <Placemark>\r\n");
            filewrite.write("    <name>Path</name>\r\n");
            filewrite.write("    <styleUrl>#lineStyle</styleUrl>\r\n");
            filewrite.write("    <MultiGeometry>\r\n");
            filewrite.write("      <LineString>\r\n");
            filewrite.write("       <altitudeMode>" + altMode + "</altitudeMode>\r\n");
            filewrite.write("        <coordinates>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /** Writes the close to the "path" section of the kml file */
    public void writePointsClose() {
        try {
            filewrite.write("        </coordinates>\r\n");
            filewrite.write("      </LineString>\r\n");
            filewrite.write("    </MultiGeometry>\r\n");
            filewrite.write("  </Placemark>\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    /**
	 * Add a coordinate in the "path" section
	 * 
	 * @param decLongitude
	 *            The decimal Longitude
	 * @param decLatitude
	 *            The decimal Latitude
	 * @param altitude
	 *            The altitude
	 */
    public void addPoint(String decLongitude, String decLatitude, double altitude) {
        try {
            filewrite.write(decLongitude + "," + decLatitude + "," + altitude + "\r\n");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /** Writes the close to the document. */
    public void closeDocument() {
        try {
            filewrite.write("</Document>\r\n");
            filewrite.write("</kml>\r\n");

            filewrite.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }
}
